﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.IO.Compression;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.Web;

namespace Common.Net
{
    public class Utilities
    {
        
        public static byte[] DeflaterExpand(byte[] compressedData)
        {
            if ((compressedData == null) || (compressedData.Length == 0))
            {
                return new byte[0];
            }
            int offset = 0;
            if (((compressedData.Length > 2) && (compressedData[0] == 120)) && (compressedData[1] == 0x9c))
            {
                offset = 2;
            }
            MemoryStream stream = new MemoryStream(compressedData, offset, compressedData.Length - offset);
            MemoryStream stream2 = new MemoryStream(compressedData.Length);
            using (DeflateStream stream3 = new DeflateStream(stream, CompressionMode.Decompress))
            {
                byte[] buffer = new byte[0x8000];
                int count = 0;
                while ((count = stream3.Read(buffer, 0, buffer.Length)) > 0)
                {
                    stream2.Write(buffer, 0, count);
                }
            }
            return stream2.ToArray();
        }

        public static byte[] GzipExpand(byte[] compressedData)
        {
            if ((compressedData == null) || (compressedData.Length == 0))
            {
                return new byte[0];
            }
            MemoryStream inner = new MemoryStream(compressedData);
            MemoryStream stream2 = new MemoryStream(compressedData.Length);
            using (GZipStream stream4 = new GZipStream(inner, CompressionMode.Decompress))
            {
                byte[] buffer2 = new byte[0x8000];
                int num2 = 0;
                while ((num2 = stream4.Read(buffer2, 0, buffer2.Length)) > 0)
                {
                    stream2.Write(buffer2, 0, num2);
                }
            }
            return stream2.ToArray();
        }

        public static byte[] doUnchunk(byte[] writeData)
        {
            if ((writeData == null) || (writeData.Length == 0))
            {
                return new byte[0];
            }
            MemoryStream stream = new MemoryStream(writeData.Length);
            int index = 0;
            bool flag = false;
            while (!flag && (index <= (writeData.Length - 3)))
            {
                int num3;
                string sInput = Encoding.ASCII.GetString(writeData, index, Math.Min(0x40, writeData.Length - index));
                int length = sInput.IndexOf("\r\n", StringComparison.Ordinal);
                if (length <= 0)
                {
                    throw new InvalidDataException("The chunked content is corrupt. Cannot find Chunk-Length in expected location. Offset: " + index.ToString());
                }
                index += length + 2;
                sInput = sInput.Substring(0, length);
                length = sInput.IndexOf(';');
                if (length > 0)
                {
                    sInput = sInput.Substring(0, length);
                }
                if (!TryHexParse(sInput, out num3))
                {
                    throw new InvalidDataException("The chunked content is corrupt. Chunk-Length was malformed." + index.ToString());
                }
                if (num3 == 0)
                {
                    flag = true;
                }
                else
                {
                    if (writeData.Length < (num3 + index))
                    {
                        throw new InvalidDataException("The chunked entity body is corrupt. The final chunk length is greater than the number of bytes remaining.");
                    }
                    stream.Write(writeData, index, num3);
                    index += num3 + 2;
                }
            }
            if (!flag)
            {
                //FiddlerApplication.DoNotifyUser("Chunked body did not terminate properly with 0-sized chunk.", "HTTP Protocol Violation");
            }
            byte[] dst = new byte[stream.Length];
            Buffer.BlockCopy(stream.GetBuffer(), 0, dst, 0, dst.Length);
            return dst;
        }  
        //[CodeDescription("Try parsing the string for a Hex-formatted int. If it fails, return false and 0 in iOutput.")]
        public static bool TryHexParse(string sInput, out int iOutput)
        {
            return int.TryParse(sInput, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo, out iOutput);
        }

        /// <summary>
        /// 规范网址
        /// </summary>
        /// <param name="BaseUrl"></param>
        /// <param name="Url"></param>
        /// <returns></returns>
        public static string NormalizeUrl(string BaseUrl, string Url)
        {
            // # 上層目錄的 sitemap.aspx 頁面
            // <a href="../sitemap.aspx
            //-----------
            // # 上兩層目錄的 default.htm 頁面
            // <a href="http://www.cnblogs.com/default.htm
            //-----------
            // # 上層目錄下的 images 目錄下的 dot 目錄下的 red.gif 檔案
            // <a href="../images/dot/red.gif
            if (Url.StartsWith("../"))
            {
                string temp = Url;
                int lastIndex = BaseUrl.LastIndexOf("/");
                BaseUrl = BaseUrl.Substring(0, lastIndex);
                while (Url.StartsWith("../"))
                {
                    lastIndex = BaseUrl.LastIndexOf("/");
                    BaseUrl = BaseUrl.Substring(0, lastIndex);
                    Url = Url.Substring(3);
                }
                return BaseUrl + "/" + Url;
            }
            string[] tokens = new string[] { "//", "#", "?", "/", "./" };
            foreach (var t in tokens)
            {
                if (Url.StartsWith(t))
                {
                    int lastIndex;
                    if (t == "./")
                    {
                        lastIndex = BaseUrl.LastIndexOf("/");
                        Url = Url.Substring(1);
                    }
                    else
                    {
                        lastIndex = BaseUrl.LastIndexOf(t);
                    }
                    if (lastIndex > 0)
                    {
                        BaseUrl = BaseUrl.Substring(0, lastIndex);
                    }
                    return BaseUrl + Url;
                }
            }
            // # 同目錄下的 step2.aspx 頁面
            // <a href="step2.aspx
            int _lastIndex = BaseUrl.LastIndexOf("/");
            if (_lastIndex > 0)
            {
                BaseUrl = BaseUrl.Substring(0, _lastIndex + 1);
            }
            return BaseUrl + Url;

            /*
            // <a href="?pageNo=2">第 2 頁</a>
            if (Url.StartsWith("?"))
            {
                int index = BaseUrl.IndexOf("?");
                if (index > 0)
                {
                    return BaseUrl.Substring(0, index) + Url;
                }
                else
                {
                    return BaseUrl + Url;
                }
            }
            
            //<img src="//l.yimg.com/tw.yimg.com/i/tw/hp/spirit/yahoo_logo.gif" />
            if (Url.StartsWith("//"))
            {
                int lastIndex = BaseUrl.LastIndexOf("//");
                if (lastIndex > 0)
                {
                    BaseUrl = BaseUrl.Substring(0, lastIndex);
                }
                return BaseUrl + Url;
            }
            // <a href="#top
            if (Url.StartsWith("#"))
            {
                int lastIndex = BaseUrl.LastIndexOf("#");
                if (lastIndex > 0)
                {
                    BaseUrl = BaseUrl.Substring(0, lastIndex);
                }
                return BaseUrl + Url;
            }*/
            /*
           // <a href="/index.aspx
           if (Url.StartsWith("/") || Url.StartsWith("./"))
           {
               int lastIndex = BaseUrl.LastIndexOf("/");
               if (lastIndex > 0)
               {
                   BaseUrl = BaseUrl.Substring(0, lastIndex);
               }
               return BaseUrl + Url;
           }
           */
            

        }

        /// <summary>
        /// 将asscii码转换成字符（含汉字）
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static string ConvertAscCodeToString(int num)
        {
            byte[] b = BitConverter.GetBytes(num);
            List<byte> listb = new List<byte>();
            for (int i = 0; i < b.Length; i++)
            {
                if (b[i] != 255 && b[i] != 0)
                {
                    listb.Add(b[i]);
                }
            }
            listb.Reverse();
            return Encoding.Default.GetString(listb.ToArray());
        }

        /// <summary>
        /// 得到字符的ascii码
        /// </summary>
        public static int Ascii(char chr)
        {
            Encoding ecode = Encoding.GetEncoding("gb18030");
            byte[] codebytes = ecode.GetBytes(chr.ToString());
            if (IsTwoBytesChar(chr))
            {
                // 双字节码为高位乘256，再加低位
                // 该为无符号码，再减65536
                return (int)codebytes[0] * 256 + (int)codebytes[1] - 65536;//=x+65536
            }    //x*<<8+y=1111
            else
            {
                return (int)codebytes[0];
            }
        }
        /// <summary>
        /// 是否为双字节字符。
        /// </summary>
        public static bool IsTwoBytesChar(char chr)
        {
            string str = chr.ToString();
            // 使用中文支持编码
            Encoding ecode = Encoding.GetEncoding("gb18030");
            if (ecode.GetByteCount(str) == 2)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 分析 url 字符串中的参数信息
        /// </summary>
        /// <param name="url">输入的 URL</param>
        /// <param name="baseUrl">输出 URL 的基础部分</param>
        /// <param name="nvc">输出分析后得到的 (参数名,参数值) 的集合</param>
        public static void ParseUrl(string url, out string baseUrl, out NameValueCollection nvc)
        {
            if (url == null)
                throw new ArgumentNullException("url");

            nvc = new NameValueCollection();
            baseUrl = "";

            if (url == "")
                return;

            int questionMarkIndex = url.IndexOf('?');

            if (questionMarkIndex == -1)
            {
                baseUrl = url;
                return;
            }
            baseUrl = url.Substring(0, questionMarkIndex);
            if (questionMarkIndex == url.Length - 1)
                return;
            string ps = url.Substring(questionMarkIndex + 1);

            // 开始分析参数对    
            Regex re = new Regex(@"(^|&)?(\w+)=([^&]+)(&|$)?", RegexOptions.Compiled);
            MatchCollection mc = re.Matches(ps);

            foreach (Match m in mc)
            {
                nvc.Add(m.Result("$2").ToLower(), m.Result("$3"));
            }
        }
         /// <summary>
        /// URL的64位编码
        /// </summary>
        /// <param name="sourthUrl"></param>
        /// <returns></returns>
        public static string Base64Encrypt(string sourthUrl)
        {
            //string eurl = HttpUtility.UrlEncode(sourthUrl);
            string eurl = Convert.ToBase64String(Encoding.Default.GetBytes(sourthUrl));
            return eurl;
        }
     
        /// <summary>
        /// URL的64位解码
        /// </summary>
        /// <param name="eStr"></param>
        /// <returns></returns>
        public static string Base64Decrypt(string eStr)
        {
            if (!IsBase64(eStr))
            {
                return eStr;
            }
            byte[] buffer = Convert.FromBase64String(eStr);
            string sourthUrl =Encoding.Default.GetString(buffer);
          //  sourthUrl = HttpUtility.UrlDecode(sourthUrl);
            return sourthUrl;
        }
        /// <summary>
        /// 是否是Base64字符串
        /// </summary>
        /// <param name="eStr"></param>
        /// <returns></returns>
        public static bool IsBase64(string eStr)
        {
            if ((eStr.Length % 4) != 0)
            {
                return false;
            }
            if (!Regex.IsMatch(eStr, "^[A-Z0-9/+=]*$", RegexOptions.IgnoreCase))
            {
                return false;
            }
            return true;
        }

    }
}
